var MobileCarousel = MobileTrapeze.extend({
    conf            : null,
    
    preload_count   : 0,
    preload_check   : null,
    
    carousel : {
        element     : null,
        width       : 0,
        height      : 0
    },
    
    slides : {
        element     : null,
        width       : 0,
        height      : 0,
        position    : 0,
        length      : 0
    },
    
    touch : {
        movement    : false,
        
        x : {
            start           : 0,
            delta           : 0,
            delta_min       : 0, // The min delta required before locking vertical scrolling
            offset          : 0,
            offset_start    : 0
        }
    },
    
    touch_carousel : function(evt) {
        switch(evt.type) {
            case 'touchstart':
                this.touch.movement         = false;
                this.touch.x.start          = evt.touches[0].clientX;
                this.touch.x.offset_start   = this.touch.x.offset;
                break;
            
            case 'touchmove':
                this.touch.movement = true;
                this.touch.x.delta = evt.touches[0].clientX - this.touch.x.start;
                
                // Lock vertical scrolling
                if ((this.touch.x.delta < 0 ? -this.touch.x.delta : this.touch.x.delta) > 10) {
                    evt.preventDefault();
                }
                
                this.move_carousel(this.touch.x.delta + this.touch.x.offset_start);
                break;
            
            case 'touchend':
                if (this.touch.movement) {
                    var change = 0;
                    if (this.touch.x.delta < -(this.touch.x.delta_min) && this.slides.position < this.slides.length-1) {
                        change = 1;
                    } else if (this.touch.x.delta > this.touch.x.delta_min && this.slides.position > 0) {
                        change = -1;
                    }
                    
                    this.transition_carousel(change);
                }
                break;
            
            default: return;
        }
    },
    
    move_carousel : function(offset) {
        this.touch.x.offset = offset;
        
        this.slides.element.style.webkitTransition = '';
        this.slides.element.style.WebkitTransform  = 'translate3d('+offset+'px, 0, 0)';
    },
    
    transition_carousel : function(change) {
        this.slides.position = this.slides.position + change;
        
        this.toggle_arrrow(this.conf.class_name.first_slide, 0);
        this.toggle_arrrow(this.conf.class_name.last_slide, this.slides.length-1);
        
        this.touch.x.offset = -(this.get_offset(this.slides.position));
        
        this.slides.element.style.webkitTransition = '-webkit-transform 300ms cubic-bezier(0.33, 0.66, 0.66, 1)';
        this.slides.element.style.WebkitTransform  = 'translate3d('+this.touch.x.offset+'px, 0, 0)';
    },
    
    get_offset : function(position) {
        return (position > 0) ? (this.carousel.width+this.conf.padding)*position : 0;
    },
    
    toggle_arrrow : function(class_name, position) {
        if (this.slides.position == position && !this.regex_class(class_name).test(this.carousel.element.className)) {
            this.carousel.element.className = this.carousel.element.className + ' ' + class_name;
        } else if (this.slides.position != position) {
            this.carousel.element.className = this.carousel.element.className.replace(this.regex_class(class_name), '');
        }
    },
    
    build_arrow : function(class_name, change) {
        var arrow = document.createElement('div');
        arrow.className = 'arrow '+class_name;
        arrow.addEventListener('click', (function() {
            this.transition_carousel(change);
        }).bind(this));
        
        return arrow;
    },
    
    resize_container : function() {
        this.carousel.width  = this.carousel.element.offsetWidth;
         
         // Limit image width
        this.slides.width = Math.min(this.conf.width, this.carousel.width);
        
        // Set slide height to proper ratio of slide width
        this.slides.height = this.conf.height*(this.slides.width/this.conf.width);
        
        // Crop container height to be no larger than 60% of screen height (landscape orientation)
        this.carousel.height = Math.round(Math.max(0, Math.min((this.slides.height), (this.get_screen_height()*0.65))));
        
        this.carousel.element.style.height = this.carousel.height+'px';
        
        // Set min delta to 15% of device width
        this.touch.x.delta_min = this.carousel.width*0.15;
        
        if (this.slides.element) {
            this.resize_slides();
        }
    },
    
    resize_slides : function() {
        [].slice.call(this.slides.element.getElementsByTagName('li')).forEach((function(slide, x) { // Convert NodeList to Array
            slide.style.left    = this.get_offset(x)+'px';
            slide.style.width   = this.carousel.width+'px';
            slide.style.height  = this.carousel.height+'px';
            
            slide.style.WebkitBackgroundSize = this.slides.width+'px '+this.slides.height+'px';
        }).bind(this));
        
        this.transition_carousel(0);
    },
    
    load_images : function () {
        this.slides.length = this.conf.slides.length;
        
        for (var i = 0; i < this.slides.length; i++) {
            this.conf.slides[i].image        = new Image();
            this.conf.slides[i].image.src    = this.conf.slides[i].src;
            this.conf.slides[i].loaded       = false;
        }
        
        this.check_images();
    },
    
    check_images : function () {
        for (var i = 0; i < this.slides.length; i++) {
            if (this.conf.slides[i].loaded == false && this.conf.slides[i].image.complete) {
                this.conf.slides[i].loaded = true;
                this.preload_count ++;
            }
        }
        
        if (this.preload_count < this.slides.length) {
            this.preload_check = setTimeout(this.check_images.bind(this), 250); // Preload not complete
        } else {
            this.load_carousel(); // Preload complete
        }
    },
    
    load_carousel : function () {
        // Remove progress meter
        var progress = document.getElementById(this.conf.selectors.progress);
        if (progress) this.carousel.element.removeChild(progress);
        
        // Build nav arrows
        this.carousel.element.appendChild(this.build_arrow('left', -1));
        this.carousel.element.appendChild(this.build_arrow('right', 1));
        
        this.slides.element = document.createElement('ul');
        this.slides.element.className = 'carousel-slides '+this.conf.class_name.first_slide;
        this.carousel.element.appendChild(this.slides.element);
        
        for (var i = 0; i < this.slides.length; i++) {
            // Wrap each word in <span class="word"> to provide wordspacing
            var split_copy = this.conf.slides[i].copy.split(' ');
            var spaced_copy = '';
            
            if (split_copy.length) {
                split_copy.forEach(function(copy, x) {
                    spaced_copy += '<span class="word">'+copy+'</span> '
                });
            }
            
            var slide = document.createElement('li');
            slide.style.backgroundImage = 'url('+this.conf.slides[i].src+')';
            if (i == 0) slide.className = 'first-child';
            this.slides.element.appendChild(slide);
            
            var slide_caption = document.createElement('div');
            slide_caption.className = 'caption';
            slide.appendChild(slide_caption);
            
            var slide_caption_anchor = document.createElement('a');
            slide_caption_anchor.href = this.conf.slides[i].url;
            slide_caption_anchor.innerHTML = spaced_copy;
            slide_caption.appendChild(slide_caption_anchor);
        }
        
        this.resize_slides();
        this.carousel.element.addEventListener('touchstart', this.touch_carousel.bind(this));
        this.carousel.element.addEventListener('touchmove', this.touch_carousel.bind(this));
        this.carousel.element.addEventListener('touchend', this.touch_carousel.bind(this));
        this.carousel.element.addEventListener('touchcancel', this.touch_carousel.bind(this));
    },
    
    init : function(options) {
        var defaults = {
            selectors : {
                carousel    : 'Carousel',
                progress    : 'CarouselProgress'
            },
            width           : 480,
            height          : 260,
            padding         : 10,
            slides          : null,
            class_name : {
                first_slide : 'first-slide',
                last_slide  : 'last-slide'
            }
        }
        this.conf = this.extend(defaults, options);
        
        this.carousel.element = document.getElementById(this.conf.selectors.carousel);
        
        // Resize
        this.resize_container();
        
        // Add listeners
        // TODOF: Verify below plays nice with Blackberry os6
        var listener = (this.is_iphone || this.is_ipad) ? 'orientationchange' : 'resize'; // Android's implemention of orientationchange is buggy
        
        window.addEventListener(listener, this.resize_container.bind(this)); // resize on orientationchange
        document.addEventListener('DOMContentLoaded', this.load_images.bind(this)); // defer image load
    }
});